package com.manage.util; /**
 * @author 汤奇
 * @version V1.0
 * @Project JavaWeb_Code
 * @Package PACKAGE_NAME
 * @Description:
 * @Date 2022/4/26 11:33
 */

import java.sql.*;
import java.util.Properties;

/**
 * 数据库工具类: 将连接数据库的一些操作, 封装成工具方法, 方便连接数据库的时候使用
 *
 * 1.提取了一些公用方法
 *
 * 2.将URL user pwd 信息都使用配置文件管理
 * */
public class DBUtil {
    //定义四个变量, 来保存配置文件中的四个值
    private static String driver;
    private static String url;
    private static String user;
    private static String pwd;

    //ThreadLocal: 可以实现线程之间的线程安全, 可以使用该对象保存一个唯一的值
    //一个ThreadLocal  对象只能保存一个值
    //来保存唯一的一个Connection
    public static ThreadLocal<Connection> local = new ThreadLocal<>();

    //读取配置文件内容
    static {
        try {
            //容器
            Properties prop = new Properties();
            //cn.myutil.DBUtil.class.get
            prop.load(DBUtil.class.getClassLoader().getResourceAsStream("bd.ini"));

            //获取配置文件中的四个属性值
            driver = prop.getProperty("driver");
            url    = prop.getProperty("url");
            user   = prop.getProperty("user");
            pwd    = prop.getProperty("pwd");
            //加载驱动
            Class.forName(driver);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //构造方法私有化
    private DBUtil(){}

    /**
     * 创建连接对象
     * */
    public static Connection getConnection(){
        Connection conn = null;
        try {
            //ThreadLocal 中是否已经有了Connection对象
            conn = local.get();
            //如果conn还没有
            if (conn == null) {
                conn = DriverManager.getConnection(url, user, pwd);
                //将生成的conn 添加到 ThreadLocal 中
                local.set(conn);
            }
            return conn;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return conn;
    }

    /**
     * 创建发射器对象
     * */
    public static PreparedStatement getStmt(Connection conn,String sql,Object ...params){
        PreparedStatement pstmt = null;
        try {
            pstmt = conn.prepareStatement(sql);

            //将传入的实参数据, 填充到 sql 语句中的问号的位置
            for (int i = 0; i < params.length; i++) {
                //动态的填充
                pstmt.setObject(i+1,params[i]);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return pstmt;
    }

    /**
     * 关闭所有的资源
     * */
    public static void closeAll(ResultSet rs,PreparedStatement pstmt,Connection conn){
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (pstmt != null) {
            try {

                pstmt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (conn != null) {
            try {
                //在事务进行的过程中不能关闭连接
                if (conn.getAutoCommit()){//true, 非事务进行中

                    conn.close();
                    //链接一旦关闭, 要从ThreadLocal 中移除
                    local.remove();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

}
